﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WaveTagLibrary
{
	public class TagInfo
	{
		public string TagName { get; set; }
		public byte[] Data { get; set; }

		public uint GetOnFileDataSize()
		{
			uint dataLength = (uint)(Data ?? new byte[0]).Length + 1;
			return dataLength + (dataLength & 1);
		}

		public async Task WriteAsync(BinaryWriter writer)
		{
			if (writer == null)
				throw new ArgumentNullException("writer");

			if (TagName == null || TagName.Length != 4)
				throw new InvalidOperationException("Invalid TagInfo");

			writer.Write(Encoding.ASCII.GetBytes(TagName));

			var buffer = Data ?? new byte[0];
			uint bufferLength = (uint)buffer.Length + 1; // +1 for null terminating zero

			writer.Write(bufferLength);
			await writer.BaseStream.WriteAsync(buffer, 0, buffer.Length);
			writer.Write((byte)0);

			if ((bufferLength & 1) == 1)
				writer.Write((byte)0); // write padding byte
		}

		public static async Task<TagInfo> ReadAsync(BinaryReader reader)
		{
			if (reader == null)
				throw new ArgumentNullException("reader");

			var tagInfo = new TagInfo();

			try
			{
				// read tag name
				tagInfo.TagName = Encoding.ASCII.GetString(reader.ReadBytes(4));

				// read data length
				var length = reader.ReadUInt32();

				// allocate buffer and read data asynchronously
				var buffer = new byte[length - 1];
				await reader.BaseStream.ReadAsync(buffer, 0, buffer.Length);
				reader.ReadByte(); // skip null terminating byte

				if ((length & 1) == 1) // odd
					reader.ReadByte(); // skip padding byte

				tagInfo.Data = buffer;
			}
			catch
			{
				return null;
			}

			return tagInfo;
		}

		private static readonly string[] infoListTags = new[]
			{
				"IARL", // Archival Location. Indicates where the subject of the file is archived.
				"IART", // Artist. Lists the artist of the original subject of the file.
				"ICMS", // Commissioned. Lists the name of the person or organization that commissioned the subject of the file.
				"ICMT", // Comments. Provides general comments about the file or the subject of the file.
				"ICOP", // Copyright. Records the copyright information for the file.
				"ICRD", // Creation date. Indicates the date the subject of the file was created.
				"ICRP", // Cropped. Indicates whether an image has been cropped.
				"IDIM", // Dimensions. Specifies the size of the original subject of the file.
				"IDPI", // Dots Per Inch. Stores the dots per inch (DPI) setting of the digitizer used to produce the file.
				"IENG", // Engineer. Stores the name of the engineer who worked on the file.
				"IGNR", // Genre. Describes the genre of the original work.
				"IKEY", // Keywords. Provides a list of keywords that refer to the file or subject of the file.
				"ILGT", // Lightness. Describes the changes in lightness settings on the digitizer required to produce the file.
				"IMED", // Medium. Describes the original subject of the file, such as, "computer image", "drawing", "lithograph", and so forth.
				"INAM", // Name. Stores the title of the subject of the file.
				"IPLT", // Palette Setting. Specifies the number of colors requested when digitizing an image.
				"IPRD", // Product. Specifies the name of the title the file was originally intended for, such as "Encyclopedia of Pacific Northwest Geography."
				"ISBJ", // Subject. Describes the file contents, such as "Aerial view of Seattle."
				"ISFT", // Software. Identifies the name of the software package used to create the file.
				"ISHP", // Sharpness. Identifies the changes in sharpness for the digitizer required to produce the file.
				"ISRC", // Source. Identifies the name of the person or organization who supplied the original subject of the file.
				"ISRF", // Source Form. Identifies the original form of the material that was digitized, such as "slide", "paper", "map", and so forth.
				"ITCH", // Technician. Identifies the technician who digitized the subject file.
			};

		public override string ToString()
		{
			var buffer = Data ?? new byte[0];
			return string.Format("{0} ({1} bytes) [{2}]", TagName, buffer.Length, Encoding.UTF8.GetString(buffer).TrimEnd('\0'));
		}
	}
}
